/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 *
 * Contributors: Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.core.internal.api;

import com.google.common.collect.Lists;

import net.sourceforge.perforce.api.IError;
import net.sourceforge.perforce.api.internal.Error;
import net.sourceforge.perforce.api.internal.Spec;
import net.sourceforge.perforce.api.internal.SpecData;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.api.IClientForm;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;

import java.util.List;
import java.util.Map;

/**
 * ClientUser object for the 'p4 client' command.
 *
 * @version $Revision: 491 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class Client extends AbstractPerforceCommand {
  //----------------------------------------------------------------------------
  // - Private Methods

  /** Stores the result of the operation. */
  private Result result;

  // --------------------------------------------------------------- Public
  // Static Factory Methods

  /**
   * Call this method to create a new Client instance.
   *
   * @return the new Client instance.
   */
  public static final Client newInstance() {
    MultiStatus status = new MultiStatus(PerforceCorePlugin.ID, IStatus.OK, "", null);

    return new Client(status);
  }

  // ------------------------------------------------------------------------
  // Private Constructors

  /**
   * Constructor for Client.
   *
   * @param status the status object.
   */
  private Client(MultiStatus status) {
    super(status);
  }

  // -------------------------------------------------------- Public Methods
  // (IClientUserDelegate)

  @Override
  public void outputStat(Map<String, ?> strDict) {
    if (strDict.containsKey("specdef") && strDict.containsKey("data")) {
      Error error = new Error();
      try {
        result.getChangeSpecDefinition().decode((String) strDict.get("specdef"), error);
        result.getChangeSpecDefinition().parse((String) strDict.get("data"),
            result.getChangeSpecData(), error, 0);

        if (error.test()) {
          getMultiStatus().merge(
              new Status(IStatus.ERROR, PerforceCorePlugin.ID, error.getGeneric(), error
                  .format(IError.EF_PLAIN), null));
        }
      } finally {
        error.dispose();
      }
    }
  }

  // ----------------------------------------------------------- Public Methods
  // (IPerforceCommand)

  public String getCommand() {
    return "client"; //$NON-NLS-1$
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Returns the client form.
   *
   * @return the client form.
   */
  public IClientForm getResult() {
    return result;
  }

  // -----------------------------------------------------------------------
  // Public Nested Classes

  /** Class representing the result of the operation. */
  public static class Result implements IClientForm {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores the changelist specification. */
    private Spec spec = new Spec();
    /** Stores the data of the specification. */
    private SpecData specData = new SpecData();

    //--------------------------------------------------------------------------
    // Public Methods

    public String getAccess() {
      return specData.get("Access");
    }

    public String getClient() {
      return specData.get("Client");
    }

    public String getDescription() {
      return specData.get("Description");
    }

    public String getHost() {
      return specData.get("Host");
    }

    public String getLineEnd() {
      return specData.get("LineEnd");
    }

    public String getOptions() {
      return specData.get("Options");
    }

    public String getOwner() {
      return specData.get("Owner");
    }

    public String getRoot() {
      return specData.get("Root");
    }

    public String getUpdate() {
      return specData.get("Update");
    }

    public String[] getView() {
      List<String> files = Lists.newArrayList();

      int i = 0;
      boolean hasMore = true;
      do {
        String filename = specData.get("View" + i++);
        if ("".equals(filename)) {
          hasMore = false;
        } else {
          files.add(filename);
        }
      } while (hasMore);

      return files.toArray(new String[files.size()]);
    }

    //--------------------------------------------------------------------------
    // ------- Methods

    SpecData getChangeSpecData() {
      return specData;
    }

    Spec getChangeSpecDefinition() {
      return spec;
    }
  }
}
